package org.aplikator.server;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.aplikator.client.widgets.BinaryFieldWidget;
import org.aplikator.server.descriptor.Entity;
import org.aplikator.server.descriptor.Property;
import org.aplikator.server.persistence.PersisterFactory;
import org.aplikator.shared.data.BinaryData;

public class FileUploadServlet extends HttpServlet {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private static final Logger LOG = Logger.getLogger(FileUploadServlet.class.getName());

    @SuppressWarnings("unchecked")
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // create a factory for disk-based file items and an upload handler
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);

        FileUploadListener listener = new FileUploadListener();
        HttpSession session = request.getSession();
        LOG.fine("FILE UPLOAD session (post) = " + session.getId());

        session.setAttribute("progress", listener);
        upload.setProgressListener(listener);
        // parse the request to retrieve the individual items
        List<FileItem> items;
        try {
            items = upload.parseRequest(request);
        } catch (FileUploadException e) {
            throw new ServletException("File upload failed", e);
        }
        // handle the individual items appropriately
        String entityId = "";
        String propertyId = "";
        int primaryKey = 0;
        String filename = "";
        for (FileItem item : items) {
            // code here to process the file
            if (item.isFormField()) {
                if (BinaryFieldWidget.ENTITY_ID.equals(item.getFieldName())) {
                    entityId = item.getString();
                    continue;
                }
                if (BinaryFieldWidget.PROPERTY_ID.equals(item.getFieldName())) {
                    propertyId = item.getString();
                    continue;
                }
                if (BinaryFieldWidget.PRIMARY_KEY_ID.equals(item.getFieldName())) {
                    primaryKey = Integer.parseInt(item.getString());
                    continue;
                }

            } else {
                filename = item.getName();
                Entity entity = (Entity) DescriptorRegistry.get().getDescriptionItem(entityId);
                Property<BinaryData> property = (Property<BinaryData>) DescriptorRegistry.get().getDescriptionItem(propertyId);
                PersisterFactory.getPersister().updateBlob(entity, property, primaryKey, filename, item.get());
            }

            LOG.fine("item = " + item);
        }

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session = request.getSession();
        FileUploadListener listener = (FileUploadListener) session.getAttribute("progress");

        if (listener != null) {
            StringBuilder msg = new StringBuilder();
            msg.append(formatSize(listener.getBytesRead()));
            msg.append("/");
            msg.append(formatSize(listener.getContentLength()));

            response.getOutputStream().write(msg.toString().getBytes());
            response.getOutputStream().close();
        }
    }

    private String formatSize(long bytes) {
        long kBytes = bytes / 1024;

        if (kBytes > 1024) {
            return kBytes / 1024 + "Mb";
        } else {
            return kBytes + "kb";
        }
    }

}
